package com.you.tomcat.bio.main;


import com.you.tomcat.bio.http.HttpRequest;
import com.you.tomcat.bio.http.HttpServlet;
import com.you.tomcat.bio.http.HttpResponse;

import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Tomcat启动服务
 */
public class BioTomcatServer {

    private final static int port = 9000;
    private ServerSocket server;

    private Properties webxml = new Properties();

    //服务的映射
    private Map<String, HttpServlet> servletMapping = new ConcurrentHashMap<String, HttpServlet>();

    public static void main(String[] args) throws Exception {
        new BioTomcatServer().start();
    }

    /**
     * 初始化配置信息
     *
     * @throws Exception
     */
    public void init() throws Exception {
        //得到当前WEB-INF类路径
        String webInf = this.getClass().getResource("/").getPath();
        FileInputStream fis = new FileInputStream(webInf + "web.properties");
        //加载web.properties配置文件
        webxml.load(fis);
        //2、配置web.xml 自己写的Servlet继承HttpServlet
        //   servlet-name
        //   servlet-class
        //   url-pattern
        //3、读取配置，url-pattern  和 Servlet建立一个映射关系
        for (Object k : webxml.keySet()) {
            String key = k.toString();
            if (key.endsWith(".url")) {
                String servletName = key.replaceAll("\\.url$", "");
                String url = webxml.getProperty(key);
                String className = webxml.getProperty(servletName + ".className");
                //单实例，多线程
                HttpServlet httpServlet = (HttpServlet) Class.forName(className).newInstance();
                servletMapping.put(url, httpServlet); //url与servletClass的映射关系
            }
        }
    }

    public void start() throws Exception {
        //1.加载配置文件
        init();
        //启动服务
        server = new ServerSocket(port);
        System.out.println("Tomcat Server 已启动，监听的端口是：" + this.port);
        //2、等待用户请求,用一个死循环来等待用户请求
        while (true) {
            Socket client = server.accept();
            try {
                //4、HTTP请求，发送的数据就是字符串，有规律的字符串（HTTP协议）
                process(client);
            } catch (Exception ex) {
                System.out.println("----处理失败，原因：-----");
                ex.printStackTrace();
            }
        }
    }

    /**
     * 每次请求的处理
     *
     * @param client
     * @throws Exception
     */
    public void process(Socket client) throws Exception {
        InputStream is = client.getInputStream();
        OutputStream os = client.getOutputStream();
        //实例化HttpRequest与HttpResponse
        HttpRequest request = new HttpRequest(is);
        HttpResponse response = new HttpResponse(os);
        //5、从协议内容中拿到URL，把相应的Servlet用反射进行实例化
        String url = request.getUrl();
        if (servletMapping.containsKey(url)) {
            HttpServlet httpServlet = servletMapping.get(url);
            httpServlet.service(request, response);
        } else {
            response.write("404-Not Found!");
        }
        os.flush();
        os.close();
        is.close();
        //关闭客户端连接
        client.close();
    }
}
